#ifndef MEM_SPACE_HEADER
#define MEM_SPACE_HEADER

// this header needs
#include <stdio.h>
#include <stdlib.h>
#include "BASIC_TYPES.h"

// first complex data type, mem_space a byte array with a byte length
// and a boolean to check if the memory was manually allocated
// all thanks to no check_if_ptr_malloc() function-like available >:[ 
typedef struct
{
  byte * ptr;
  umax size;
} mem_space;
// size of the structure
#define MEM_SPACE_SIZE sizeof(mem_space)

// error codes for the memory allocator
typedef enum
{
  MEM_SPACE_NO_ERR,       // nothing has happened
  MEM_SPACE_TB_FULL,      // the table is full
  MEM_SPACE_CALLOC_FAIL,  // a call to calloc() failed
} mem_space_err;

// var_mem_space enum
// the second variable types enum
typedef enum
{
  VAR_MEM_SPACE = VAR_BASIC_TYPES + 1,
  VAR_MEM_SPACE_ERR,
} var_mem_space;

// size of the pointer table
#define MEM_SPACE_TB_LENGTH 50
umax MEM_SPACE_TB_FREE_SPACE = MEM_SPACE_TB_LENGTH;
// global alloc error
mem_space_err MEM_SPACE_GLOB_ERR = MEM_SPACE_NO_ERR;

// memory space table
// table defined to keep track of all variables based on mem_space
// (everything that will come after this header basically)
// All memory allocated pointers will be stored in this table.
// All pointers in this table will be NULL at first.
// This table helps (at least helps me) to avoid memory leaks
// and to avoid making so much memory allocations at once.
// also the name it has sounds very interesting and advanced
mem_space MEM_SPACE_TB[MEM_SPACE_TB_LENGTH] = {{NULL, 0}};

// basic functions
mem_space * create_mem_space(umax size);
umax free_mem_space(mem_space * space);
umax print_mem_space(byte * src, umax size);

// other functions
void print_mem_space_tb_err(void);

#include "MEM_SPACE.c"

#endif // MEM_SPACE_HEADER
